export enum RegisterType {
  coil = 1,
  discreteInput = 2,
  holding = 3,
  input = 4,
}

export interface RegisterAddress {
  registerType: number;
  startAddress: number;
  endAddress: number;
}

export interface IntPointRegister {
  signed: number;
  unsigned: number;
  hex: string;
  bin: string;
  value: number;
}

export interface LongPointRegister {
  longABCD: number,  // 原始顺序 (ABCD)
  longCDAB: number,  // 高低16位交换 (CDAB)
  longBADC: number,  // 字节内高低字节交换 (BADC)
  longDCBA: number,  // 完全逆序 (DCBA)
  value: number;
}

export interface FloatPointRegister {
  floatABCD: number;  // 原始顺序 (ABCD)
  floatCDAB: number;  // 高低16位交换 (CDAB)
  floatBADC: number;  // 字节内高低字节交换 (BADC)
  floatDCBA: number;  // 完全逆序 (DCBA)
  value: number;
}

export enum InnerDecode {
  SignedShort = "SignedShort",
  UnsignedShort = "UnsignedShort",
  LongABCD = "LongABCD",
  LongCDAB = "LongCDAB",
  LongBADC = "LongBADC",
  LongDCBA = "LongDCBA",
  FloatABCD = "FloatABCD",
  FloatCDAB = "FloatCDAB",
  FloatBADC = "FloatBADC",
  FloatDCBA = "FloatDCBA"
}

// 转换函数，根据 InnerDecode 类型将字节数组转换为对应类型的值
export function convertBytes(decodeType: InnerDecode, bytes: Uint8Array): number {
  const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);

  switch (decodeType) {
    case InnerDecode.SignedShort:
      return dataView.getInt16(0, false); // 大端序
    case InnerDecode.UnsignedShort:
      return dataView.getUint16(0, false); // 大端序
    case InnerDecode.LongABCD:
      return dataView.getInt32(0, false); // 大端序
    case InnerDecode.LongCDAB: {
      const swappedBytes = new Uint8Array(4);
      swappedBytes.set(bytes.subarray(2, 4), 0);
      swappedBytes.set(bytes.subarray(0, 2), 2);
      return new DataView(swappedBytes.buffer).getInt32(0, false);
    }
    case InnerDecode.LongBADC: {
      const swappedBytes = new Uint8Array(4);
      swappedBytes[0] = bytes[1];
      swappedBytes[1] = bytes[0];
      swappedBytes[2] = bytes[3];
      swappedBytes[3] = bytes[2];
      return new DataView(swappedBytes.buffer).getInt32(0, false);
    }
    case InnerDecode.LongDCBA: {
      const swappedBytes = new Uint8Array(4);
      swappedBytes.set(bytes.reverse());
      return new DataView(swappedBytes.buffer).getInt32(0, false);
    }
    case InnerDecode.FloatABCD:
      return dataView.getFloat32(0, false); // 大端序
    case InnerDecode.FloatCDAB: {
      const swappedBytes = new Uint8Array(4);
      swappedBytes.set(bytes.subarray(2, 4), 0);
      swappedBytes.set(bytes.subarray(0, 2), 2);
      return new DataView(swappedBytes.buffer).getFloat32(0, false);
    }
    case InnerDecode.FloatBADC: {
      const swappedBytes = new Uint8Array(4);
      swappedBytes[0] = bytes[1];
      swappedBytes[1] = bytes[0];
      swappedBytes[2] = bytes[3];
      swappedBytes[3] = bytes[2];
      return new DataView(swappedBytes.buffer).getFloat32(0, false);
    }
    case InnerDecode.FloatDCBA: {
      const swappedBytes = new Uint8Array(4);
      swappedBytes.set(bytes.reverse());
      return new DataView(swappedBytes.buffer).getFloat32(0, false);
    }
    default:
      throw new Error(`Unsupported decode type: ${decodeType}`);
  }
}

// 根据 InnerDecode 类型将输入值转换为对应类型的值

export function convertValue(value: any, dataType: InnerDecode) {

  const strValue = String(value).trim();
  if (strValue === "") {
    return 0;
  }

  const buffer = new ArrayBuffer(4);
  const dataView = new DataView(buffer);
  let numValue = 0;

  if (dataType.startsWith("Long")) {
    numValue = parseInt(strValue, 10);
    numValue = Math.max(-2147483648, Math.min(2147483647, numValue));
  } else if (dataType.startsWith("Float")) {
    numValue = parseFloat(strValue);
  } else if (dataType === InnerDecode.SignedShort) {
    numValue = parseInt(strValue, 10);
    numValue = Math.max(-32768, Math.min(32767, numValue));
  } else if (dataType === InnerDecode.UnsignedShort) {
    numValue = parseInt(strValue, 10);
    numValue = Math.max(0, Math.min(65535, numValue));
  }

  // 先按大端序存储
  if (dataType.startsWith("Long")) {
    dataView.setInt32(0, numValue, false);
  } else if (dataType.startsWith("Float")) {
    dataView.setFloat32(0, numValue, false);
  } else if (dataType === InnerDecode.SignedShort) {
    dataView.setInt16(0, numValue, false);
  } else if (dataType === InnerDecode.UnsignedShort) {
    dataView.setUint16(0, numValue, false);
  }

  const bytes = new Uint8Array(buffer);

  // 根据不同字节序交换字节
  switch (dataType) {
    case InnerDecode.LongABCD:
    case InnerDecode.FloatABCD:
      [bytes[0], bytes[1], bytes[2], bytes[3]] = [bytes[2], bytes[3], bytes[0], bytes[1]];
      break;
    case InnerDecode.LongCDAB:
    case InnerDecode.FloatCDAB:
      [bytes[0], bytes[1], bytes[2], bytes[3]] = [bytes[2], bytes[3], bytes[0], bytes[1]];
      break;
    case InnerDecode.LongBADC:
    case InnerDecode.FloatBADC:
      [bytes[0], bytes[1], bytes[2], bytes[3]] = [bytes[1], bytes[0], bytes[3], bytes[2]];
      break;
    case InnerDecode.LongDCBA:
    case InnerDecode.FloatDCBA:
      bytes.reverse();
      break;
  }

  // 重新读取处理后的值
  if (dataType.startsWith("Long")) {
    return new DataView(bytes.buffer).getInt32(0, false);
  } else if (dataType.startsWith("Float")) {
    return new DataView(bytes.buffer).getFloat32(0, false);
  } else if (dataType === InnerDecode.SignedShort) {
    return new DataView(bytes.buffer).getInt16(0, false);
  } else if (dataType === InnerDecode.UnsignedShort) {
    return new DataView(bytes.buffer).getUint16(0, false);
  }

  return numValue;
}


// 获取所有枚举值（数组形式）
export const InnerDecodeList = Object.values(InnerDecode);

// 根据类型返回占用的寄存器个数
export function getRegisterCount(decodeType: InnerDecode): number {
  switch (decodeType) {
    case InnerDecode.SignedShort:
    case InnerDecode.UnsignedShort:
      return 1; // 短整型占用1个寄存器

    case InnerDecode.LongABCD:
    case InnerDecode.LongCDAB:
    case InnerDecode.LongBADC:
    case InnerDecode.LongDCBA:
    case InnerDecode.FloatABCD:
    case InnerDecode.FloatCDAB:
    case InnerDecode.FloatBADC:
    case InnerDecode.FloatDCBA:
      return 2; // 长整型和浮点型占用2个寄存器

    default:
      throw new Error(`Unknown decode type: ${decodeType}`);
  }
}

export enum ModbusFunctionCode {
  READ_COIL_REGISTERS = 1,
  READ_DISCRETE_INPUT_REGISTERS = 2,
  READ_HOLDING_REGISTERS = 3,
  READ_INPUT_REGISTERS = 4,
  WRITE_COIL_REGISTERS = 5,
  WRITE_HOLDING_REGISTERS = 6,
  WRITE_MULTIPLE_COILS = 15,
  WRITE_MULTIPLE_REGISTERS = 16,
}

export enum WriteMethod {
  Single = 1,
  Multiple = 2
}
